from fastapi import APIRouter, Depends, UploadFile, File, Form, Request, Header
from fastapi.responses import JSONResponse
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List, Optional

from config.get_db import get_db
from module_admin.service.login_service import LoginService
from module_speech.service.speech_service import SpeechService
from module_speech.service.speech_client_service import ClientUserService
from module_speech.entity.vo.speech_vo import (
    SpeechRecognizeRequest, SpeechRecognizeResponse,
    SpeechQueryModel, SpeechDeleteModel
)
from utils.response_util import ResponseUtil
from utils.page_util import PageResponseModel
from utils.log_util import logger
from utils.speech_auth_util import SpeechAuthUtil


# 系统用户路由（需要JWT认证）
speechController = APIRouter(prefix='/speech', dependencies=[Depends(LoginService.get_current_user)])


async def get_user_info_from_request(request: Request, api_key: Optional[str] = Header(None, alias="X-API-Key")) -> dict:
    """
    从请求中获取用户信息，支持JWT和API Key两种认证方式
    
    Returns:
        dict: 包含用户信息的字典
    """
    # 优先使用JWT认证（系统用户）
    if hasattr(request.state, 'current_user') and request.state.current_user:
        return {
            'user_type': 'system',
            'user_id': request.state.current_user.user_id,
            'user_info': request.state.current_user,
            'is_admin': getattr(request.state.current_user, 'admin', False)
        }
    
    # 如果有API Key，尝试客户端用户认证
    if api_key:
        try:
            client_user = await SpeechAuthUtil.verify_api_key(api_key, request)
            if client_user:
                return {
                    'user_type': 'client',
                    'user_id': None,
                    'client_user_id': client_user['id'],
                    'user_info': client_user,
                    'is_admin': False
                }
        except Exception as e:
            logger.warning(f"API Key认证失败: {str(e)}")
    
    # 如果都没有，抛出认证错误
    raise HTTPException(status_code=401, detail="认证失败")


@speechController.post('/upload-recognize', response_model=SpeechRecognizeResponse)
async def upload_and_recognize_audio(
    request: Request,
    db: AsyncSession = Depends(get_db),
    file: UploadFile = File(..., description="音频文件"),
    language: Optional[str] = Form(default='zh', description="语言类型：zh/en/auto"),
    model_name: Optional[str] = Form(default='sensevoice-small', description="识别模型名称"),
    use_vad: Optional[bool] = Form(default=True, description="是否使用语音活动检测"),
    use_punc: Optional[bool] = Form(default=True, description="是否添加标点符号"),
    use_itn: Optional[bool] = Form(default=True, description="是否使用逆文本归一化"),
    hotwords: Optional[str] = Form(default=None, description="热词列表，用逗号分隔"),
    session_id: Optional[str] = Form(default=None, description="会话ID"),
    callback_url: Optional[str] = Form(default=None, description="回调URL（客户端用户可用）"),
    api_key: Optional[str] = Header(None, alias="X-API-Key", description="API密钥（客户端用户使用）")
):
    """
    上传音频文件并进行语音识别
    支持系统用户（JWT认证）和客户端用户（API Key认证）
    """
    try:
        # 获取用户信息
        user_info = await get_user_info_from_request(request, api_key)
        
        # 处理热词
        hotword_list = []
        if hotwords:
            hotword_list = [word.strip() for word in hotwords.split(',') if word.strip()]
        
        # 构造请求参数
        request_params = SpeechRecognizeRequest(
            language=language,
            model_name=model_name,
            use_vad=use_vad,
            use_punc=use_punc,
            use_itn=use_itn,
            hotwords=hotword_list,
            session_id=session_id,
            callback_url=callback_url if user_info['user_type'] == 'client' else None
        )
        
        # 执行识别
        result = await SpeechService.upload_and_recognize_audio(
            db=db,
            file=file,
            user_id=user_info.get('user_id'),
            client_user_id=user_info.get('client_user_id'),
            user_type=user_info['user_type'],
            request_params=request_params
        )
        
        logger.info(f"{user_info['user_type']}用户成功识别音频文件: {file.filename}")
        return ResponseUtil.success(data=result)
        
    except Exception as e:
        logger.error(f"音频识别失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


@speechController.get('/records', response_model=PageResponseModel)
async def get_speech_records(
    request: Request,
    db: AsyncSession = Depends(get_db),
    query_params: SpeechQueryModel = Depends(SpeechQueryModel.as_query),
    api_key: Optional[str] = Header(None, alias="X-API-Key")
):
    """
    获取语音识别记录列表
    支持系统用户和客户端用户的数据隔离
    """
    try:
        # 获取用户信息
        user_info = await get_user_info_from_request(request, api_key)
        
        # 设置用户过滤条件
        if user_info['user_type'] == 'system':
            # 系统用户：管理员可以看所有记录，普通用户只能看自己的
            if not user_info['is_admin']:
                query_params.user_id = user_info['user_id']
                query_params.user_type = 'system'
        else:
            # 客户端用户：只能看自己的记录
            query_params.client_user_id = user_info['client_user_id']
            query_params.user_type = 'client'
        
        result = await SpeechService.get_speech_records(db, query_params)
        
        logger.info(f"{user_info['user_type']}用户获取语音记录列表成功")
        return ResponseUtil.success(
            data=PageResponseModel(
                rows=result['rows'],
                total=result['total']
            )
        )
        
    except Exception as e:
        logger.error(f"获取语音记录失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


@speechController.get('/records/{speech_id}')
async def get_speech_record_detail(
    speech_id: int,
    request: Request,
    db: AsyncSession = Depends(get_db),
    api_key: Optional[str] = Header(None, alias="X-API-Key")
):
    """
    获取语音识别记录详情
    支持双用户体系的权限控制
    """
    try:
        # 获取用户信息
        user_info = await get_user_info_from_request(request, api_key)
        
        # 设置权限检查参数
        if user_info['user_type'] == 'system':
            check_user_id = user_info['user_id'] if not user_info['is_admin'] else None
            check_client_user_id = None
        else:
            check_user_id = None
            check_client_user_id = user_info['client_user_id']
        
        result = await SpeechService.get_speech_record_detail(
            db=db,
            speech_id=speech_id,
            user_id=check_user_id,
            client_user_id=check_client_user_id,
            user_type=user_info['user_type']
        )
        
        logger.info(f"{user_info['user_type']}用户获取语音记录详情成功: {speech_id}")
        return ResponseUtil.success(data=result)
        
    except Exception as e:
        logger.error(f"获取语音记录详情失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


@speechController.delete('/records')
async def delete_speech_records(
    request: Request,
    delete_params: SpeechDeleteModel,
    db: AsyncSession = Depends(get_db),
    api_key: Optional[str] = Header(None, alias="X-API-Key")
):
    """
    删除语音识别记录
    支持双用户体系的权限控制
    """
    try:
        # 获取用户信息
        user_info = await get_user_info_from_request(request, api_key)
        
        # 设置权限检查参数
        if user_info['user_type'] == 'system':
            check_user_id = user_info['user_id'] if not user_info['is_admin'] else None
            check_client_user_id = None
        else:
            check_user_id = None
            check_client_user_id = user_info['client_user_id']
        
        success = await SpeechService.delete_speech_records(
            db=db,
            delete_params=delete_params,
            user_id=check_user_id,
            client_user_id=check_client_user_id,
            user_type=user_info['user_type']
        )
        
        if success:
            logger.info(f"{user_info['user_type']}用户删除语音记录成功: {delete_params.speech_ids}")
            return ResponseUtil.success(message="删除成功")
        else:
            return ResponseUtil.error(message="删除失败")
        
    except Exception as e:
        logger.error(f"删除语音记录失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


@speechController.get('/models')
async def get_supported_models(
    request: Request,
    api_key: Optional[str] = Header(None, alias="X-API-Key")
):
    """
    获取支持的语音识别模型列表
    支持双用户体系，客户端用户可能有模型权限限制
    """
    try:
        # 获取用户信息
        user_info = await get_user_info_from_request(request, api_key)
        
        # 获取可用模型列表
        if user_info['user_type'] == 'client':
            # 客户端用户需要检查模型权限
            models = await SpeechService.get_available_models_for_client(
                client_user_id=user_info['client_user_id']
            )
        else:
            # 系统用户可以使用所有模型
            models = await SpeechService.get_supported_models()
        
        # 构造模型信息
        model_info = []
        for model_name in models:
            model_info.append({
                'name': model_name,
                'display_name': _get_model_display_name(model_name),
                'streaming': _is_streaming_model(model_name),
                'languages': _get_model_languages(model_name)
            })
        
        return ResponseUtil.success(data=model_info)
        
    except Exception as e:
        logger.error(f"获取模型列表失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


@speechController.post('/session/{session_id}/clear')
async def clear_speech_session(
    session_id: str,
    request: Request,
    api_key: Optional[str] = Header(None, alias="X-API-Key")
):
    """
    清除语音识别会话缓存
    支持双用户体系
    """
    try:
        # 获取用户信息
        user_info = await get_user_info_from_request(request, api_key)
        
        # 清除会话（可以根据用户类型添加不同的逻辑）
        success = await SpeechService.clear_session(session_id)
        
        if success:
            logger.info(f"{user_info['user_type']}用户清除会话成功: {session_id}")
            return ResponseUtil.success(message="会话已清除")
        else:
            return ResponseUtil.error(message="会话清除失败")
        
    except Exception as e:
        logger.error(f"清除会话失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


# ==================== 新增：客户端用户专用接口 ====================
@speechController.get('/quota', dependencies=[])
async def get_quota_info(
    request: Request,
    db: AsyncSession = Depends(get_db),
    api_key: str = Header(..., alias="X-API-Key")
):
    """
    获取客户端用户配额信息
    仅支持API Key认证的客户端用户
    """
    try:
        # 验证API Key
        client_user = await SpeechAuthUtil.verify_api_key(api_key, request)
        if not client_user:
            return ResponseUtil.error(message="无效的API密钥", code=401)
        
        # 获取配额信息
        quota_info = await ClientUserService.get_quota_info(db, client_user['id'])
        
        return ResponseUtil.success(data=quota_info)
        
    except Exception as e:
        logger.error(f"获取配额信息失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


@speechController.get('/usage/statistics', dependencies=[])
async def get_usage_statistics(
    request: Request,
    db: AsyncSession = Depends(get_db),
    api_key: str = Header(..., alias="X-API-Key"),
    start_date: Optional[str] = None,
    end_date: Optional[str] = None
):
    """
    获取客户端用户使用统计
    仅支持API Key认证的客户端用户
    """
    try:
        # 验证API Key
        client_user = await SpeechAuthUtil.verify_api_key(api_key, request)
        if not client_user:
            return ResponseUtil.error(message="无效的API密钥", code=401)
        
        # 获取使用统计
        usage_stats = await ClientUserService.get_usage_statistics(
            db=db,
            client_user_id=client_user['id'],
            start_date=start_date,
            end_date=end_date
        )
        
        return ResponseUtil.success(data=usage_stats)
        
    except Exception as e:
        logger.error(f"获取使用统计失败: {str(e)}")
        return ResponseUtil.error(message=str(e))


# ==================== 辅助函数 ====================
def _get_model_display_name(model_name: str) -> str:
    """获取模型显示名称"""
    model_names = {
        'sensevoice-small': 'SenseVoice Small（通用多语言）',
        'paraformer-zh': 'Paraformer 中文（离线）',
        'paraformer-zh-streaming': 'Paraformer 中文（流式）'
    }
    return model_names.get(model_name, model_name)


def _is_streaming_model(model_name: str) -> bool:
    """判断是否为流式模型"""
    streaming_models = ['paraformer-zh-streaming']
    return model_name in streaming_models


def _get_model_languages(model_name: str) -> List[str]:
    """获取模型支持的语言列表"""
    model_languages = {
        'sensevoice-small': ['zh', 'en', 'yue', 'ja', 'ko'],
        'paraformer-zh': ['zh'],
        'paraformer-zh-streaming': ['zh']
    }
    return model_languages.get(model_name, ['zh']) 